/*
 * vm.c
 *
 *  Created on: 03/10/2013
 *      Author: vitor
 */

#include "vm.h"

void initializeVM(vmInfo* vm, executableFile program) {
	memset(vm, 0, sizeof(vmInfo));
	vm->running = 1;
	vm->reg[SP] = BASE_STACK;
	vm->reg[BP] = BASE_STACK;
	vm->pc = program.executionStartAddress;

	memcpy(vm->mem, program.program, MEM_SIZE * sizeof(char));
}

void decodeInstruction(instrInfo* instruction, unsigned int instructionBytecode) {
	instruction->opcode = (instructionBytecode & 0xFC000000) >> 26;
	instruction->rs = (instructionBytecode & 0x03E00000) >> 21;
	instruction->rt = (instructionBytecode & 0x001F0000) >> 16;
	instruction->rd = (instructionBytecode & 0x0000F800) >> 11;
	instruction->funct = (instructionBytecode & 0x000007FF);
	instruction->imm = (instructionBytecode & 0x0000FFFF);
}

unsigned int readWordFromPC(vmInfo* vm) {
	unsigned int instructionBytecode = 0;
	int i = 0;

	for (i = 0; i < 4; i++) {
		instructionBytecode = instructionBytecode << 8 | vm->mem[vm->pc];
		vm->pc++;
	}

	return instructionBytecode;
}

void fetchAndDecode(vmInfo* vm, instrInfo* instruction) {
	unsigned int instructionBytecode;

	instructionBytecode = readWordFromPC(vm);

	decodeInstruction(instruction, instructionBytecode);
}

void execute(vmInfo* vm, instrInfo instruction) {
	if (instruction.opcode == 0) {
		RInstrArray[instruction.funct](vm, instruction);
	} else {
		IInstrArray[instruction.opcode](vm, instruction);
	}
}
